import { Bi } from "@/module-00-codebase/pkg-01-container";
import { Throwable } from "@/module-00-codebase/pkg-02-tool";
import { Field, PropertyField, PropertyGroup } from "@/module-00-codebase/pkg-08-entity/field-entity";

export class PropertyDescription {
  public getPropertyGroup(orefType: any, collectType: string): PropertyGroup {
    return Bi.dataExchange.parse(Bi.dataExchange.serialize((propertyGroupsMap[orefType] || {})[collectType] || null));
  }
  public getProperties(orefType: any, collectType: string): string[] {
    return Bi.dataExchange.parse(Bi.dataExchange.serialize((propertiesMap[orefType] || {})[collectType] || null));
  }
  public get(): string[];
  public get(type: any): Field[];
  public get(type: any, column: string): Field;
  public get(type?: any, column?: string) {
    if (arguments.length === 0 || type === undefined) {
      return Object.keys(descriptionMap);
    } else if (arguments.length === 1 || column === undefined) {
      if (!descriptionMap[type]) {
        return null;
      } else {
        return Object.keys(descriptionMap[type]).map(key => descriptionMap[type][key].clone());
      }
    } else {
      const columnChain = Bi.utils.splitProperties(column) as string[];
      let pd: Field | undefined = undefined;
      let orefType: string | undefined = type;
      const labels: any[] = [];
      const cascadables = [] as boolean[];
      if (columnChain.length === 0) {
        pd = new PropertyField("", "", "oref");
        pd.orefType = type;
      } else {
        for (let i = 0; i < columnChain.length; i++) {
          if (!orefType) {
            Throwable("Impossible Error: No orefType");
          } else if (/[0-9]+/.test(columnChain[i])) {
            if (!!pd) {
              pd = pd.clone();
              pd.mode.validations.length = 0;
            }
            //   if (!!pd) {
            //     labels.pop();
            //     labels.push(pd.singularLabel);
            //   }
            //   labels.push(`::${Number.parseInt(columnChain[i], 10) + 1}`);
          } else {
            pd = descriptionMap[orefType][columnChain[i]];
            if (!pd) break;
            if (i < columnChain.length - 1) cascadables.push(pd.mode.cascadable);
            labels.push(pd.label);
            orefType = pd.orefType;
          }
        }
      }
      if (!!pd) {
        const pdres = pd.clone();
        pdres.declaringType = type;
        pdres.name = column;
        pdres.label = labels.join(" ");
        pdres.mode.readOnly = !cascadables.reduce((a, b) => a && b, !pdres.mode.readOnly);
        if (pdres.izArray === true && column.lastIndexOf(".") > 0 && /[0-9]+/.test(column.substring(column.lastIndexOf(".") + 1))) {
          pdres.izArray = false;
        }
        return pdres;
      } else {
        return Throwable("Cannot find attribute [" + column + "] in [" + type + "]");
      }
    }
  }
}
export const dependencies = () => ["Utils", "Rpc"];
export const initializing = async () => {
  const res = await Bi.rpc.send({ url: "/statics/poEntities", method: "GET", loading: "Loading property description..." });
  descriptionMap = res.data.data.descriptionMap as any;
  propertiesMap = res.data.data.propertiesMap as any;
  propertyGroupsMap = res.data.data.propertyGroupsMap as any;
  const clone = new PropertyField("none", "none");
  Object.keys(descriptionMap).forEach(key => {
    Object.keys(descriptionMap[key]).forEach(key0 => {
      const field = descriptionMap[key][key0];
      const copy = { ...clone, ...field };
      Object.assign(field, copy);
    });
  });
};

let descriptionMap: { [key: string]: { [key: string]: Field } };
// <"list" | "add" | "edit" | "name" | "criteria">
let propertiesMap: { [key: string]: { [key: string]: string[] } };
let propertyGroupsMap: { [key: string]: { [key: string]: PropertyGroup[] } };
